/*
 * wc.c
 *
 * Copyright (C) 2019 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <mlcrt.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <monolithium.h>

handle_t __CRT_PRIVATE(get_raw_handle)(int fd);

static char *wd_path = NULL;

char *__CRT_PUBLIC(getcwd)(char *buf, size_t size)
{
    return __CRT_PUBLIC(strncpy)(buf, wd_path, size);
}

char *__CRT_PUBLIC(getwd)(char *buf)
{
    return __CRT_PUBLIC(strcpy)(buf, wd_path);
}

char *__CRT_PUBLIC(get_current_dir_name)(void)
{
    return __CRT_PUBLIC(strdup)(wd_path);
}

int __CRT_PUBLIC(fchdir)(int fd)
{
    char path[MAX_PATH];
    handle_t handle = __CRT_PRIVATE(get_raw_handle)(fd);

    sysret_t ret = syscall_query_file(handle, FILE_INFO_NAME, path, sizeof(path));

    if (ret != ERR_SUCCESS)
    {
        switch (ret)
        {
        case ERR_FORBIDDEN:
            __CRT_PUBLIC(errno) = EACCES;

        default:
            __CRT_PUBLIC(errno) = __CRT_PRIVATE(translate_error)(ret);
        }

        return -1;
    }

    if (wd_path)
    {
        __CRT_PUBLIC(free)(wd_path);
        wd_path = NULL;
    }

    wd_path = __CRT_PUBLIC(strdup)(path);
    return 0;
}

int __CRT_PUBLIC(chdir)(const char *path)
{
    int fd = __CRT_PUBLIC(open)(path, O_RDONLY, 0);
    if (fd < 0) return -1;

    int ret = __CRT_PUBLIC(fchdir)(fd);
    __CRT_PUBLIC(close)(fd);
    return ret;
}
